package top.heue.utils.data.helper

import android.content.Context
import android.util.Log
import io.objectbox.BoxStore
import io.objectbox.BoxStoreBuilder
import io.objectbox.Property
import io.objectbox.query.QueryBuilder
import java.lang.Thread.sleep
import java.util.*
import kotlin.concurrent.thread

object DataHelper {
    private var box: BoxStore? = null
    val boxStore: BoxStore get() = box!!

    init {
        //检查
        thread {
            sleep(3000)
            if (box == null) Log.w(
                "DataHelper",
                "程序没有执行必要的 init() 方法, DataHelper 将不可用"
            )
        }
    }

    @JvmStatic
    fun init(context: Context, boxStoreBuilder: BoxStoreBuilder) {
        box?.close()
        box = boxStoreBuilder.androidContext(context).build()
    }
    /*fun init(context: Context) {
        //box = MyObjectBox.builder().androidContext(context).build()

        //防止忘记，初始化检查
        if (box == null) L.w("BoxStore 尚未初始化，请调用")
    }*/

    inline fun <reified T> addOrSet(bean: T): Long {
        return boxStore.boxFor(T::class.java).put(bean)
    }

    inline fun <reified T> addOrSet(beans: Collection<T>) {
        boxStore.boxFor(T::class.java).put(beans)
    }

    inline fun <reified T> removeAll() {
        boxStore.boxFor(T::class.java).removeAll()
    }

    inline fun <reified T> removeById(vararg ids: Long) {
        removeById<T>(ids.toList())
    }

    inline fun <reified T> removeById(ids: Collection<Long>) {
        boxStore.boxFor(T::class.java).removeByIds(ids)
    }

    inline fun <reified T> removeByObject(bean: T) {
        boxStore.boxFor(T::class.java).remove(bean)
    }

    inline fun <reified T> findAll(): List<T> {
        return boxStore.boxFor(T::class.java).query().build().find()
    }

    /** 按条件查找，默认以第一个参数的降序（orderDesc()）排序（即反序输出，新的在最上面）输出*/
    inline fun <reified T> findByAny(
        vararg pairs: Pair<Property<T>, Any>,
        isOrderDesc: Boolean = false,
        page: Long = 0,
        pageSize: Long = 0
    ): List<T> {
        //equal等于,greater大于,less小于,and和,or或
        var q = boxStore.boxFor(T::class.java).query()
        for (pair in pairs) {
            val k = pair.first
            val v = pair.second
            q = when (v) {
                is Long -> q.equal(k, v)
                is String -> q.equal(k, v, QueryBuilder.StringOrder.CASE_INSENSITIVE)
                is Boolean -> q.equal(k, v)
                is ByteArray -> q.equal(k, v)
                is Date -> q.equal(k, v)
                is Double -> q.equal(k, v, 0.1)
                else -> throw IllegalArgumentException("不支持的查找格式")
            }
        }
        //反序输出
        if (isOrderDesc)
            q = q.orderDesc(pairs[0].first)
        if (page != 0L && pageSize != 0L) {
            //分页输出
            return q.build().find((page - 1) * pageSize, pageSize)
        }
        //全部输出
        return q.build().find()
    }

    /** 获取一个数据，如果为空就返回null*/
    inline fun <reified T> findOneOrNull(vararg pairs: Pair<Property<T>, Any>): T? {
        val data = findByAny(*pairs)
        if (data.isEmpty()) return null
        return data[0]
    }

    /** 获取一个数据，如果为空则执行给定语句返回新的*/
    inline fun <reified T> findOneOrExecute(
        vararg pairs: Pair<Property<T>, Any>,
        exec: (() -> T)
    ): T {
        return findOneOrNull(*pairs) ?: return exec()
    }

}